package jcdatabase;

import java.io.*;
import java.util.Vector;

public class JCTable
{

    static final int maximumNumberOfRecords = 99;
    boolean insertNotPermitted;
    final String recordsExceededMessage = "\nInsert ignored. 100 records cannot be exceeded with the non-commercial version of JCDatabase. Please visit www.digitalscores.com/JCDatabase for registration instructions.\n";
    public String tableName;
    public JCDataDefinition definition;
    public final String dataFileExtension = ".dat";
    private RandomAccessFile file;
    private final int maximumNumberOfResults = 0x186a0;
    public int cacheSizeInBytes;
    private Vector cache;
    protected int numberOfCachedRecords;

    public JCTable(String s)
    {
	insertNotPermitted = false;
	numberOfCachedRecords = 0;
	definition = new JCDataDefinition(s);
	tableName = s;
	cacheSizeInBytes = 100000;
	createMemoryCache();
    }

    public JCTable(String s, int i)
    {
	insertNotPermitted = false;
	numberOfCachedRecords = 0;
	definition = new JCDataDefinition(s);
	tableName = s;
	cacheSizeInBytes = i;
	createMemoryCache();
    }

    public void comit()
    {
    }

    public void destroy()
    {
	closeDataFile();
    }

    private void createMemoryCache()
    {
	cache = new Vector(cacheSizeInBytes / definition.rowSizeInBytes + 1);
	cache.clear();
	openDataFile();
	try
	{
	    file.seek(0L);
	    numberOfCachedRecords = 0;
	    while(file.getFilePointer() <= file.length() - (long)definition.rowSizeInBytes)
	    {
		JCRow jcrow = getNextJCRow();
		if(file.getFilePointer() < (long)cacheSizeInBytes)
		{
		    cache.add(jcrow);
		    numberOfCachedRecords++;
		}
	    }
	    Debug.println("   " + numberOfCachedRecords + " records cached from table " + tableName);
	}
	catch(IOException ioexception)
	{
	    Debug.error("General error while creating cache");
	    return;
	}
	closeDataFile();
    }

    public JCRow[] select()
    {
	return select(definition.columnName[0], "<>", "");
    }

    public JCRow[] select(String s, String s1, int i)
    {
	return select(s, s1, "" + i);
    }

    public JCRow[] select(String s, String s1, float f)
    {
	return select(s, s1, "" + f);
    }

    public JCRow[] select(String s, String s1, String s2)
    {
	if(!validateOperator(s1))
	{
	    Debug.error("Bad operator '" + s1 + "' in delete statement - no rows will be deleted");
	    return null;
	}
	int i = getColumnNumber(s);
	boolean flag = false;
	if(definition.dataType[i] == 0 || definition.dataType[i] == 1)
	    flag = true;
	JCRow ajcrow[] = new JCRow[0x186a0];
	int j = 0;
	int k = 0;
	openDataFile();
	try
	{
	    file.seek(0L);
	    do
	    {
		JCRow jcrow;
		if(k < numberOfCachedRecords)
		{
		    jcrow = (JCRow)cache.elementAt(k);
		    if(k == numberOfCachedRecords - 1)
			file.seek(numberOfCachedRecords * definition.rowSizeInBytes);
		} else
		{
		    if(file.getFilePointer() > file.length() - (long)definition.rowSizeInBytes)
			break;
		    jcrow = getNextJCRow();
		}
		String s3 = jcrow.getString(i);
		boolean flag1 = false;
		if(definition.dataType[i] == 0 || definition.dataType[i] == 1)
		{
		    int i1 = Integer.parseInt(s3);
		    int j1 = Integer.parseInt(s2);
		    if(s1.equals("=") || s1.equals("=="))
		    {
			if(i1 == j1)
			    flag1 = true;
		    } else
		    if(s1.equals(">"))
		    {
			if(i1 > j1)
			    flag1 = true;
		    } else
		    if(s1.equals("<"))
		    {
			if(i1 < j1)
			    flag1 = true;
		    } else
		    if(s1.equals(">="))
		    {
			if(i1 >= j1)
			    flag1 = true;
		    } else
		    if(s1.equals("<="))
		    {
			if(i1 <= j1)
			    flag1 = true;
		    } else
		    if((s1.equals("<>") || s1.equals("!=")) && i1 != j1)
			flag1 = true;
		} else
		if(definition.dataType[i] == 3)
		{
		    float f = Float.parseFloat(s3);
		    float f1 = Float.parseFloat(s2);
		    if(s1.equals("=") || s1.equals("=="))
		    {
			if(f == f1)
			    flag1 = true;
		    } else
		    if(s1.equals(">"))
		    {
			if(f > f1)
			    flag1 = true;
		    } else
		    if(s1.equals("<"))
		    {
			if(f < f1)
			    flag1 = true;
		    } else
		    if(s1.equals(">="))
		    {
			if(f >= f1)
			    flag1 = true;
		    } else
		    if(s1.equals("<="))
		    {
			if(f <= f1)
			    flag1 = true;
		    } else
		    if((s1.equals("<>") || s1.equals("!=")) && f != f1)
			flag1 = true;
		} else
		{
		    String s4 = s3;
		    String s5 = s2;
		    if(s1.equals("=") || s1.equals("=="))
		    {
			if(s4.equals(s5))
			    flag1 = true;
		    } else
		    if(s1.equals(">"))
		    {
			if(s4.length() > s5.length())
			    flag1 = true;
		    } else
		    if(s1.equals("<"))
		    {
			if(s4.length() < s5.length())
			    flag1 = true;
		    } else
		    if(s1.equals(">="))
		    {
			if(s4.length() >= s5.length())
			    flag1 = true;
		    } else
		    if(s1.equals("<="))
		    {
			if(s4.length() <= s5.length())
			    flag1 = true;
		    } else
		    if((s1.equals("!=") || s1.equals("<>")) && s4.length() != s5.length())
			flag1 = true;
		}
		if(flag1)
		    ajcrow[j++] = jcrow;
		if(j >= 0x186a0)
		{
		    Debug.error("\nInsert ignored. 100 records cannot be exceeded with the non-commercial version of JCDatabase. Please visit www.digitalscores.com/JCDatabase for registration instructions.\n");
		    return null;
		}
		k++;
	    } while(true);
	}
	catch(IOException ioexception)
	{
	    Debug.error("General error in select, table " + tableName);
	    return null;
	}
	closeDataFile();
	JCRow ajcrow1[] = new JCRow[j];
	for(int l = 0; l < j; l++)
	    ajcrow1[l] = ajcrow[l];

	return ajcrow1;
    }

    public JCRow[] select(String s, String s1, String s2, String s3, String s4, String s5, String s6)
    {
	if(!s3.equals("AND") && !s3.equals("OR"))
	{
	    Debug.error("Combination '" + s3 + "' in select method not valid - must be either 'AND' or " + "'OR'. No records will be returned");
	    return null;
	} else
	{
	    return setRelationship(select(s, s1, s2), s3, select(s4, s5, s6));
	}
    }

    public JCRow[] setRelationship(JCRow ajcrow[], String s, JCRow ajcrow1[])
    {
	if(!s.equals("AND") && !s.equals("OR"))
	{
	    Debug.error("Combination '" + s + "' in select method not valid - must be either 'AND' or " + "'OR'. No records will be returned");
	    System.exit(1);
	    return null;
	}
	JCRow ajcrow2[] = new JCRow[0x186a0];
	int i = 0;
	if(ajcrow == null)
	    return null;
	if(ajcrow.length == 0)
	    return new JCRow[0];
	if(ajcrow1 == null)
	    return null;
	if(ajcrow1.length == 0)
	    return new JCRow[0];
	int j = ajcrow[0].table.columnNumberOfAUTOINTEGER();
	int k = ajcrow1[0].table.columnNumberOfAUTOINTEGER();
	if(tableHasAColumnOfTypeAUTOINTEGER())
	{
	    for(int l = 0; l < ajcrow.length; l++)
	    {
		for(int i1 = 0; i1 < ajcrow1.length; i1++)
		    if(ajcrow[l].getInt(j) == ajcrow1[i1].getInt(k))
			ajcrow2[i++] = ajcrow[l];

	    }

	    if(s.equals("AND"))
	    {
		JCRow ajcrow3[] = new JCRow[i];
		for(int k1 = 0; k1 < i; k1++)
		    ajcrow3[k1] = ajcrow2[k1];

		return ajcrow3;
	    }
	    int j1 = 0;
	    JCRow ajcrow4[] = new JCRow[(ajcrow.length + ajcrow1.length) - i];
	    for(int l1 = 0; l1 < ajcrow.length; l1++)
		ajcrow4[j1++] = ajcrow[l1];

	    for(int i2 = 0; i2 < ajcrow1.length; i2++)
	    {
		boolean flag = false;
		for(int j2 = 0; j2 < i; j2++)
		{
		    if(ajcrow1[i2].getInt(k) != ajcrow2[j2].getInt("ID"))
			continue;
		    flag = true;
		    break;
		}

		if(!flag)
		    ajcrow4[j1++] = ajcrow1[i2];
	    }

	    if(j1 != (ajcrow.length + ajcrow1.length) - i)
		Debug.error("Unknown error with union algorithm");
	    return ajcrow4;
	} else
	{
	    Debug.error("Table " + tableName + " must have column of unique values of type AUTOINTEGER before union or " + "conjunction select statements can be executed. No records returned.");
	    System.exit(1);
	    return null;
	}
    }

    public JCRow[] select(String s, String s1, JCRow ajcrow[])
    {
	if(ajcrow.length == 0)
	{
	    JCRow ajcrow1[] = new JCRow[0];
	    return ajcrow1;
	}
	JCTable jctable = ajcrow[0].table;
	int i = getColumnNumber(s);
	int j = jctable.getColumnNumber(s1);
	if(i == -1)
	{
	    Debug.error("Critical error with join select method: Column " + s + " from " + tableName + " not found");
	    System.exit(1);
	}
	if(j == -1)
	{
	    Debug.error("Critical error with join select method: Column " + s1 + " from " + jctable.tableName + " not found");
	    System.exit(1);
	}
	JCRow ajcrow2[] = new JCRow[0x186a0];
	int k = 0;
	openDataFile();
	try
	{
	    file.seek(0L);
	    while(file.getFilePointer() <= file.length() - (long)definition.rowSizeInBytes)
	    {
		JCRow jcrow = getNextJCRow();
		String s2 = jcrow.getString(i);
		boolean flag = false;
		for(int i1 = 0; i1 < ajcrow.length; i1++)
		{
		    if(!s2.equals(ajcrow[i1].getString(j)))
			continue;
		    flag = true;
		    break;
		}

		if(flag)
		    ajcrow2[k++] = jcrow;
		if(k >= 0x186a0)
		{
		    Debug.error("\nInsert ignored. 100 records cannot be exceeded with the non-commercial version of JCDatabase. Please visit www.digitalscores.com/JCDatabase for registration instructions.\n");
		    return null;
		}
	    }
	}
	catch(IOException ioexception)
	{
	    Debug.error("General error in join select, table " + tableName);
	    return null;
	}
	closeDataFile();
	JCRow ajcrow3[] = new JCRow[k];
	for(int l = 0; l < k; l++)
	    ajcrow3[l] = ajcrow2[l];

	return ajcrow3;
    }

    public JCRow[] select(String s, String s1, JCTable jctable)
    {
	return select(s, s1, jctable.select());
    }

    private JCRow getNextJCRow()
    {
	JCRow jcrow = new JCRow(this);
	try
	{
	    for(int i = 0; i < definition.numberOfColumns; i++)
		switch(definition.dataType[i])
		{
		case 0: // '\0'
		case 1: // '\001'
		    int j = file.readInt();
		    jcrow.setInt(i, j);
		    break;

		case 3: // '\003'
		    float f = file.readFloat();
		    jcrow.setFloat(i, f);
		    break;

		case 2: // '\002'
		    byte abyte0[] = new byte[definition.dataLength[i]];
		    file.read(abyte0);
		    String s = new String(abyte0);
		    jcrow.setString(i, s);
		    break;

		default:
		    Debug.error("Unknown data-type found in getNextJCRow");
		    return null;
		}

	    return jcrow;
	}
	catch(IOException ioexception)
	{
	    Debug.error("General error in getNextRow, table " + tableName);
	}
	return null;
    }

    public boolean validateOperator(String s)
    {
	return s.equals("=") || s.equals("==") || s.equals(">") || s.equals("<") || s.equals(">=") || s.equals("<=") || s.equals("!=") || s.equals("<>");
    }





    private boolean tableHasAColumnOfTypeAUTOINTEGER()
    {
	for(int i = 0; i < definition.numberOfColumns; i++)
	    if(definition.dataType[i] == 1)
		return true;

	return false;
    }

    private int columnNumberOfAUTOINTEGER()
    {
	for(int i = 0; i < definition.numberOfColumns; i++)
	    if(definition.dataType[i] == 1)
		return i;

	return -1;
    }



    public int delete(JCRow ajcrow[])
    {
	if(ajcrow == null)
	    return -1;
	if(ajcrow.length == 0)
	    return 0;
	String s = ajcrow[0].table.tableName;
	if(!tableName.equals(s))
	{
	    Debug.error("delete(JCRow[] rowsToDelete) is being executed from table " + tableName + " but rowsToDelete is from table " + s + ". The tables " + "need to match.");
	    System.exit(1);
	}
	if(!tableHasAColumnOfTypeAUTOINTEGER())
	{
	    Debug.error("delete(JCRow[] rowsToDelete) is being executed from table " + tableName + " that does not have a column of type AUTOINTEGER.");
	    System.exit(1);
	}
	int i = 0;
	openDataFile();
	try
	{
	    file.seek(0L);
	    while(file.getFilePointer() <= file.length() - (long)definition.rowSizeInBytes)
	    {
		long l = file.getFilePointer();
		for(int j = 0; j < definition.numberOfColumns; j++)
		{
		    if(definition.dataType[j] == 1)
		    {
			boolean flag = false;
			int k = file.readInt();
			for(int i1 = 0; i1 < ajcrow.length; i1++)
			{
			    if(ajcrow[i1].getInt(j) != k)
				continue;
			    flag = true;
			    break;
			}

			if(!flag)
			    continue;
			file.seek(l);
			deleteRowAtPointer();
			file.setLength(file.length() - (long)definition.rowSizeInBytes);
			i++;
			break;
		    }
		    file.skipBytes(definition.dataLength[j]);
		}

	    }
	}
	catch(IOException ioexception)
	{
	    Debug.error("General error in delete(JCRow rowsToDelete[]), table " + tableName);
	    return -1;
	}
	closeDataFile();
	if(cacheSizeInBytes > 0)
	    createMemoryCache();
	return i;
    }


    public int delete(String s, String s1, int i)
    {
	return delete(s, s1, "" + i);
    }

    public int delete(String s, String s1, float f)
    {
	return delete(s, s1, "" + f);
    }

    public int delete(String s, String s1, String s2)
    {
	if(!validateOperator(s1))
	{
	    Debug.error("Bad operator '" + s1 + "' in delete statement - no rows will be deleted");
	    return 0;
	}
	int i = getColumnNumber(s);
	int j = 0;
	openDataFile();
	try
	{
	    file.seek(0L);
	    while(file.getFilePointer() <= file.length() - (long)definition.rowSizeInBytes)
	    {
		long l = file.getFilePointer();
		for(int k = 0; k < definition.numberOfColumns; k++)
		{
		    if(k == i)
		    {
			boolean flag = false;
			if(definition.dataType[i] == 0 || definition.dataType[i] == 1)
			{
			    int i1 = file.readInt();
			    int j1 = Integer.parseInt(s2);
			    if((s1.equals("=") || s1.equals("==")) && i1 == j1)
				flag = true;
			    if(s1.equals(">") && i1 > j1)
				flag = true;
			    if(s1.equals("<") && i1 < j1)
				flag = true;
			    if((s1.equals("!=") || s1.equals("<>")) && i1 != j1)
				flag = true;
			    if(s1.equals(">=") && i1 >= j1)
				flag = true;
			    if(s1.equals("<=") && i1 <= j1)
				flag = true;
			} else
			if(definition.dataType[i] == 3)
			{
			    float f = file.readFloat();
			    float f1 = Float.parseFloat(s2);
			    if((s1.equals("=") || s1.equals("==")) && f == f1)
				flag = true;
			    if(s1.equals(">") && f > f1)
				flag = true;
			    if(s1.equals("<") && f < f1)
				flag = true;
			    if((s1.equals("!=") || s1.equals("<>")) && f != f1)
				flag = true;
			    if(s1.equals(">=") && f >= f1)
				flag = true;
			    if(s1.equals("<=") && f <= f1)
				flag = true;
			} else
			{
			    byte abyte0[] = new byte[definition.dataLength[k]];
			    file.read(abyte0);
			    String s3 = new String(abyte0);
			    s3 = stringWithTrailingCharactersTrimmed(s3, ' ');
			    String s4 = s2;
			    if((s1.equals("=") || s1.equals("==")) && s3.equals(s4))
				flag = true;
			    if(s1.equals(">") && s3.length() > s4.length())
				flag = true;
			    if(s1.equals("<") && s3.length() < s4.length())
				flag = true;
			    if((s1.equals("!=") || s1.equals("<>")) && !s3.equals(s4))
				flag = true;
			    if(s1.equals(">=") && s3.length() >= s4.length())
				flag = true;
			    if(s1.equals("<=") && s3.length() <= s4.length())
				flag = true;
			}
			if(!flag)
			    continue;
			file.seek(l);
			deleteRowAtPointer();
			file.setLength(file.length() - (long)definition.rowSizeInBytes);
			j++;
			break;
		    }
		    file.skipBytes(definition.dataLength[k]);
		}

	    }
	}
	catch(IOException ioexception)
	{
	    Debug.error("General error in delete, table " + tableName);
	    return -1;
	}
	closeDataFile();
	if(cacheSizeInBytes > 0)
	    createMemoryCache();
	return j;
    }

    private void deleteRowAtPointer()
    {
	try
	{
	    long l = file.getFilePointer();
	    file.seek(file.length() - (long)definition.rowSizeInBytes);
	    JCRow jcrow = getNextJCRow();
	    file.seek(l);
	    insertRowAtPointerWithoutAutonumber(jcrow);
	    file.seek(l);
	}
	catch(IOException ioexception)
	{
	    Debug.error("General error in deleteRowAtPointer, table " + tableName);
	}
    }

    public int update(String s, int i, String s1, String s2, int j)
    {
	return update(s, "" + i, s1, s2, "" + j);
    }

    public int update(String s, String s1, String s2, String s3, int i)
    {
	return update(s, s1, s2, s3, "" + i);
    }

    public int update(String s, int i, String s1, String s2, String s3)
    {
	return update(s, "" + i, s1, s2, s3);
    }

    public int update(String s, String s1, String s2, String s3)
    {
	return update("!MultipleUpdate!", s, s1, s2, s3);
    }

    public int update(String s, String s1, String s2, String s3, String s4)
    {
	if(!validateOperator(s3))
	{
	    Debug.error("Bad operator '" + s3 + "' in update statement - no rows will be updated");
	    return 0;
	}
	int i = getColumnNumber(s2);
	int j = 0;
	openDataFile();
	try
	{
	    file.seek(0L);
	    for(boolean flag = false; !flag;)
	    {
		long l = file.getFilePointer();
		for(int k = 0; k < definition.numberOfColumns; k++)
		{
		    if(k == i)
		    {
			boolean flag1 = false;
			if(definition.dataType[i] == 0 || definition.dataType[i] == 1)
			{
			    int i1 = file.readInt();
			    int j1 = Integer.parseInt(s4);
			    if((s3.equals("=") || s3.equals("==")) && i1 == j1)
				flag1 = true;
			    if(s3.equals(">") && i1 > j1)
				flag1 = true;
			    if(s3.equals("<") && i1 < j1)
				flag1 = true;
			    if((s3.equals("!=") || s3.equals("<>")) && i1 != j1)
				flag1 = true;
			    if(s3.equals(">=") && i1 >= j1)
				flag1 = true;
			    if(s3.equals("<=") && i1 <= j1)
				flag1 = true;
			} else
			if(definition.dataType[i] == 3)
			{
			    float f = file.readFloat();
			    float f1 = Float.parseFloat(s4);
			    if((s3.equals("=") || s3.equals("==")) && f == f1)
				flag1 = true;
			    if(s3.equals(">") && f > f1)
				flag1 = true;
			    if(s3.equals("<") && f < f1)
				flag1 = true;
			    if((s3.equals("!=") || s3.equals("<>")) && f != f1)
				flag1 = true;
			    if(s3.equals(">=") && f >= f1)
				flag1 = true;
			    if(s3.equals("<=") && f <= f1)
				flag1 = true;
			} else
			{
			    byte abyte0[] = new byte[definition.dataLength[k]];
			    file.read(abyte0);
			    String s5 = new String(abyte0);
			    s5 = stringWithTrailingCharactersTrimmed(s5, ' ');
			    String s6 = s4;
			    if((s3.equals("=") || s3.equals("==")) && s5.equals(s6))
				flag1 = true;
			    if(s3.equals(">") && s5.length() > s6.length())
				flag1 = true;
			    if(s3.equals("<") && s5.length() < s6.length())
				flag1 = true;
			    if((s3.equals("!=") || s3.equals("<>")) && !s5.equals(s6))
				flag1 = true;
			    if(s3.equals(">=") && s5.length() >= s6.length())
				flag1 = true;
			    if(s3.equals("<=") && s5.length() <= s6.length())
				flag1 = true;
			}
			if(!flag1)
			    continue;
			if(s.equals("!MultipleUpdate!"))
			{
			    String as[] = JCDataDefinition.breakSentenceIntoWords(s1, " ");
			    for(int k1 = 0; k1 < as.length; k1++)
			    {
				String as1[] = JCDataDefinition.breakSentenceIntoWords(as[k1], "=");
				if(as1.length != 2)
				{
				    Debug.error("Critical error: Message '" + s1 + "' contains a word separated " + "by spaces that does not contain an '=' character.");
				    System.exit(1);
				} else
				{
				    file.seek(l);
				    updateRowAtPointer(getColumnNumber(as1[0]), as1[1]);
				}
			    }

			    j++;
			} else
			{
			    file.seek(l);
			    updateRowAtPointer(getColumnNumber(s), s1);
			    j++;
			}
			if(l + (long)definition.rowSizeInBytes >= file.length())
			    flag = true;
			else
			    file.seek(l + (long)definition.rowSizeInBytes);
			break;
		    }
		    file.skipBytes(definition.dataLength[k]);
		}

		if(l + (long)definition.rowSizeInBytes >= file.length())
		    flag = true;
	    }

	}
	catch(IOException ioexception)
	{
	    Debug.error("General error in update, table " + tableName);
	    return -1;
	}
	closeDataFile();
	if(cacheSizeInBytes > 0)
	    createMemoryCache();
	return j;
    }

    public int insert(JCRow jcrow)
    {
	if(insertNotPermitted)
	{
	    Debug.error("\nInsert ignored. 100 records cannot be exceeded with the non-commercial version of JCDatabase. Please visit www.digitalscores.com/JCDatabase for registration instructions.\n");
	    return -1;
	} else
	{
	    openDataFile();
	    goToEndOfFile();
	    int i = insertRowAtPointer(jcrow);
	    closeDataFile();
	    return i;
	}
    }

    public int insert(String s)
    {
	if(insertNotPermitted)
	{
	    Debug.error("\nInsert ignored. 100 records cannot be exceeded with the non-commercial version of JCDatabase. Please visit www.digitalscores.com/JCDatabase for registration instructions.\n");
	    return -1;
	}
	JCRow jcrow = new JCRow(this);
	String as[] = JCDataDefinition.breakSentenceIntoWords(s, " ");
	for(int i = 0; i < as.length; i++)
	{
	    String as1[] = JCDataDefinition.breakSentenceIntoWords(as[i], "=");
	    if(as1.length != 2)
	    {
		Debug.error("Critical error: Message '" + s + "' contains a word separated " + "by spaces that does not contain an '=' character.");
		System.exit(1);
	    } else
	    {
		jcrow.setString(as1[0], as1[1]);
	    }
	}

	return insert(jcrow);
    }

    private int insertRowAtPointer(JCRow jcrow)
    {
	if(insertNotPermitted)
	{
	    Debug.error("\nInsert ignored. 100 records cannot be exceeded with the non-commercial version of JCDatabase. Please visit www.digitalscores.com/JCDatabase for registration instructions.\n");
	    return -1;
	}
	int i = 0;
	try
	{
	    for(int j = 0; j < definition.numberOfColumns; j++)
		switch(definition.dataType[j])
		{
		case 0: // '\0'
		    file.writeInt(jcrow.getInt(j));
		    break;

		case 1: // '\001'
		    i = getMaxInteger(j) + 1;
		    definition.maximumInteger[j]++;
		    file.writeInt(i);
		    break;

		case 3: // '\003'
		    file.writeFloat(jcrow.getFloat(j));
		    break;

		case 2: // '\002'
		    String s = fixedLength(jcrow.getString(j), definition.dataLength[j]);
		    file.writeBytes(s);
		    break;
		}

	    return i;
	}
	catch(IOException ioexception)
	{
	    Debug.error("General error in insertRowAtPointer, table " + tableName);
	}
	return -1;
    }

    private void insertRowAtPointerWithoutAutonumber(JCRow jcrow)
    {
	if(insertNotPermitted)
	{
	    Debug.error("\nInsert ignored. 100 records cannot be exceeded with the non-commercial version of JCDatabase. Please visit www.digitalscores.com/JCDatabase for registration instructions.\n");
	    return;
	}
	try
	{
	    for(int i = 0; i < definition.numberOfColumns; i++)
		switch(definition.dataType[i])
		{
		case 0: // '\0'
		case 1: // '\001'
		    file.writeInt(jcrow.getInt(i));
		    break;

		case 3: // '\003'
		    file.writeFloat(jcrow.getFloat(i));
		    break;

		case 2: // '\002'
		    String s = fixedLength(jcrow.getString(i), definition.dataLength[i]);
		    file.writeBytes(s);
		    break;
		}

	    return;
	}
	catch(IOException ioexception)
	{
	    Debug.error("General error in insertRowAtPointer, table " + tableName);
	}
    }

    private boolean updateRowAtPointer(int i, String s)
    {
	try
	{
	    for(int j = 0; j < definition.numberOfColumns; j++)
		if(j == i)
		{
		    if(definition.dataType[j] == 2)
		    {
			String s1 = fixedLength(s, definition.dataLength[j]);
			file.writeBytes(s1);
		    } else
		    if(definition.dataType[j] == 3)
			file.writeFloat(Float.parseFloat(s));
		    else
			file.writeInt(Integer.parseInt(s));
		} else
		{
		    file.skipBytes(definition.dataLength[j]);
		}

	    return true;
	}
	catch(IOException ioexception)
	{
	    Debug.error("General error in update, table " + tableName);
	}
	return false;
    }

    public static String stringWithTrailingCharactersTrimmed(String s, char c)
    {
	if(s.equals(""))
	    return "";
	do
	{
	    char c1 = s.substring(s.length() - 1, s.length()).toCharArray()[0];
	    if(c1 != c)
		return s;
	    s = s.substring(0, s.length() - 1);
	} while(s.length() != 0);
	return "";
    }

    public static String fixedLength(String s, int i)
    {
	int j = s.length();
	if(j == i)
	    return s;
	if(j < i)
	{
	    for(int k = j; k < i; k++)
		s = s + " ";

	    return s;
	} else
	{
	    return s.substring(0, i);
	}
    }

    public int maxInteger(String s)
    {
	openDataFile();
	int i = getMaxInteger(s);
	closeDataFile();
	return i;
    }

    private int getMaxInteger(String s)
    {
	return getMaxInteger(getColumnNumber(s));
    }

    private int getMaxInteger(int i)
    {
	int j = 0;
	if(definition.dataType[i] != 0 && definition.dataType[i] != 1)
	    return -1;
	if(definition.maximumInteger[i] == -1)
	{
	    int k = 0;
	    try
	    {
		long l1 = file.getFilePointer();
		file.seek(0L);
		while(file.getFilePointer() <= file.length() - (long)definition.rowSizeInBytes)
		{
		    if(++j > 99)
			insertNotPermitted = true;
		    for(int i1 = 0; i1 < definition.numberOfColumns; i1++)
			if(i1 == i)
			{
			    int l = file.readInt();
			    if(l > k)
				k = l;
			} else
			{
			    file.skipBytes(definition.dataLength[i1]);
			}

		}
		file.seek(l1);
	    }
	    catch(IOException ioexception)
	    {
		Debug.error("General error in getMaxInteger, table " + tableName);
	    }
	    definition.maximumInteger[i] = k;
	}
	return definition.maximumInteger[i];
    }

    private void openDataFile()
    {
	try
	{
	    file = new RandomAccessFile(tableName + ".dat", "rw");
	}
	catch(IOException ioexception)
	{
	    Debug.error("General error in open, table " + tableName);
	}
    }

    private synchronized void closeDataFile()
    {
	try
	{
	    file.close();
	}
	catch(IOException ioexception)
	{
	    Debug.error("General error in close, table " + tableName);
	}
    }

    private void goToEndOfFile()
    {
	try
	{
	    file.seek(file.length());
	}
	catch(IOException ioexception)
	{
	    Debug.error("General error in goToEndOfFile, table " + tableName);
	}
    }

    private int getColumnNumber(String s)
    {
	for(int i = 0; i < definition.numberOfColumns; i++)
	    if(definition.columnName[i].equalsIgnoreCase(s))
		return i;

	Debug.error("ERROR: Column name '" + s + "' not found");
	return -1;
    }

    public void printAllData()
    {
	JCRow ajcrow[] = select();
	for(int i = 0; i < definition.numberOfColumns; i++)
	    System.out.print(definition.columnName[i] + "\t");

	System.out.print("\n");
	for(int j = 0; j < ajcrow.length; j++)
	{
	    for(int k = 0; k < definition.numberOfColumns; k++)
		System.out.print(ajcrow[j].getString(k) + "\t");

	    System.out.print("\n");
	}

    }
}
